#ifndef _GAME_H
#define _GAME_H

class Level;
class Camera;
class Hunter;
class Character;
class Rect;
class Circle;
struct Point2;
class Object;
class mrKeyboard;
class Source;

#define GAME_WON	1
#define GAME_ON		2
#define GAME_LOST	3

#define NONE		0x00000000
#define FLOORS		0x00000001
#define SLOPES		0x00000002
#define LEVEL		0x00000004
#define PLATFORMS	0x00000008
#define CIRCLES		0x00000010
#define ZOMBIES		0x00000011
#define KOLOBOKS	0x00000012
#define BIRDS		0x00000014

class Game{

public:
	static Game* Instance();

	bool standsCircleAtLevel(Level* level, float radius, Point2* position, Point2* n, Object** object);
	bool collideCircleToLevel(Level* level, float radius, Point2* position, Point2* v, float* t, Point2* n, unsigned int flag, Object** object);
	bool standsRectAtLevel(Level* level, Rect* rect, Point2* position, Point2* n, Object** object);
	bool collideRectToLevel(Level* level, Rect* rect, Point2* position, Point2* v, float* t, Point2* n, unsigned int flag, Object** object);

	void processKeys(Level* level, Character* player, mrKeyboard* kbd);
	int runGameLogic(Level* level, Character* player, Camera* cam, float dt);
//	void srcPlay(Object* object, Character* character);
//	Source* createSource(int state, int material);
//	void srcPlay(Character* character);

	bool trilinear;
	bool keys[256];			// Array Used For The Keyboard Routine
	int key_up;
	int key_down;
	int key_left;
	int key_right;
	int key_attack;
	int key_special;
	bool sound;
	int scores;
	int cycle_time;
	bool jump_ready;

protected:
   Game();
private:
	static Game* _instance;

//	enum{PLATFORMS =0, FLOORS =1, SLOPES =2, CIRCLES =4};
//	Source* createRikSource();
//	Source* createGroundSource();
//	Source* Game::createHitSource();
	bool collideRectToCircles(Level* level, Rect* rect, Point2* position, Point2* V, Point2* n, float* t_min, Object** object);
	bool collideRectToSlopes(Level* level, Rect* rect, Point2* position, Point2* v, Point2* n, float* t_min, Object** object);
	bool collideRectToFloors(Level* level, Rect* rect, Point2* position, Point2* v, float* t_min, Object** object);
	bool collideRectToLevelVert(Level* level, Rect* rect, Point2* position, Point2* v, float* t_tmp, Point2* n);
	bool collideRectToPlatforms(Level* level, Rect* rect, Point2* position, Point2* v, float* t_min, Point2* n, Object** object);
	bool standsRectAtFloors(Level* level, Rect* rect, Point2* position, Object** object);
	bool standsRectAtPlatforms(Level* level, Rect* rect, Point2* position, Object** object);
	bool standsRectAtSlopes(Level* level, Rect* rect, Point2* position, Object** object);

	bool collideCircleToPlatforms(Level* level, float radius, Point2* position, Point2* v, float* t_min, Point2* n, Object** object);
	bool standsCircleAtPlatforms(Level* level, float radius, Point2* position, Object** object);

	void updateZombies(Level* level, Character* player, Camera* camera, float dt);
	void updateBirds(Level* level, Character* player, float dt);
	void updateKoloboks(Level* level, Character* player, float dt);
	void* collidePointToLevel(Level* level, Point2* o, Point2* d, Point2* p, Point2* normal, unsigned int flag, unsigned int* type);
	int checkLogics(Level* level, Character* player);
	void updateClouds(Level* level, Camera* camera, float dt);
	void updateProjectiles(Level* level, float dt);
	void createZombies(Level* level);

	int _stand_prediction;
	float _tan_133;
};

#endif